package com.blame.javacup.hortalezablamers.utils.pases;

import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Vector;

import org.javahispano.javacup.model.command.Command;
import org.javahispano.javacup.model.command.CommandHitBall;
import org.javahispano.javacup.model.command.CommandMoveTo;
import org.javahispano.javacup.model.engine.GameSituations;
import org.javahispano.javacup.model.util.Constants;

import com.blame.javacup.hortalezablamers.utils.pases.simulador.engine.CommandHitBallSimulated;
import com.blame.javacup.hortalezablamers.utils.pases.simulador.engine.IndiceYPosicion;
import com.blame.javacup.hortalezablamers.utils.pases.simulador.engine.SimuladorPases;

public class PaseAlHueco {
	
	public static Random random = new Random();

	public static List<Command> pasar(GameSituations gs, int indicePasador) {
		
		SimuladorPases sp = new SimuladorPases(gs);
		
		// calculamos cuantas iteraciones de diferencia hay entre la 
		// recuperacion del balon propia y la del rival para todos los comandos
		Vector<CommandHitBallSimulated> comandosSimulados = new Vector<CommandHitBallSimulated>();
		double deltaAngulo = 7.5;
		double anguloAPorteria = Math.toDegrees(gs.ballPosition().angle(Constants.centroArcoSup));
		double angulo = (anguloAPorteria - 90) + (deltaAngulo * 2);
		for(int i = 0; i < 20; i++) { // indice de angulos
			for(double j = 4; j < 10; j++) { // indice de potencias
				CommandHitBall chb = new CommandHitBall(indicePasador, angulo, (j/10.)+0.05, false);
				int simulacionPeorBajo = Integer.MIN_VALUE;
				for(int k = 0; k < 10; k++) { // indice de estadistica de pase
					int simulacionActual = sp.simularPase(chb);
					if(simulacionActual > simulacionPeorBajo)
						simulacionPeorBajo = simulacionActual;
				}
				comandosSimulados.add(new CommandHitBallSimulated(gs, chb, simulacionPeorBajo));

				chb = new CommandHitBall(indicePasador, angulo, (j/10.)+0.05, 40);
				int simulacionPeorAlto = Integer.MIN_VALUE;
				for(int k = 0; k < 10; k++) { // indice de estadistica de pase
					int simulacionActual = sp.simularPase(chb);
					if(simulacionActual > simulacionPeorAlto)
						simulacionPeorAlto = simulacionActual;
				}
				comandosSimulados.add(new CommandHitBallSimulated(gs, chb, simulacionPeorAlto));
			}
			angulo += deltaAngulo;
		}

		CommandHitBallSimulated chbsToReturn = null;
		
		// filtramos los que tienen la diferencia de iteraciones en positivo
		Vector<CommandHitBallSimulated> comandosSimuladosBeneficiosos = new Vector<CommandHitBallSimulated>();
		for(CommandHitBallSimulated chbs : comandosSimulados)
			if(chbs.getIterationDifference() < -2)
				comandosSimuladosBeneficiosos.add(chbs);
		
		// si no hay ningun pase posible devolvemos null, y si lo hay devolvemos el mejor pase
		if(comandosSimuladosBeneficiosos.isEmpty()) {
//			return null;
			Vector<CommandHitBallSimulated> comandosSimuladosAlLimite = new Vector<CommandHitBallSimulated>();
			for(CommandHitBallSimulated chbsAlLimite : comandosSimulados)
				if(chbsAlLimite.getIterationDifference() < 0)
					comandosSimuladosAlLimite.add(chbsAlLimite);
			
			if(comandosSimuladosAlLimite.isEmpty())
				return null;

			// obtiene uno de los comandos con mayor potencia
			chbsToReturn = obtenerMejorPase(gs, comandosSimuladosAlLimite);
		}
		else {
			chbsToReturn = obtenerMejorPase(gs, comandosSimuladosBeneficiosos);
		}
//		System.out.println(
//				"\nInd: " + indicePasador + 
//				"\nIt: " + gs.iteration() + 
//				"\nPos: " + gs.ballPosition() + 
//				"\nItDiff: " + chbsToReturn.getIterationDifference() + 
//				"\nAng: " + chbsToReturn.getChb().getAngle() + 
//				"\nPot: " + chbsToReturn.getChb().getHitPower() +
//				"\nAngV: " + chbsToReturn.getChb().getVerticalAngle()
//				);
		
		// TODO: si el receptor es el mismo que el pasador, modifico la potencia para hacer un autopase preciso
		
		// calculo la posicion a la que debe correr el receptor
		IndiceYPosicion iyp = sp.obtenerIntercepcionPase(chbsToReturn.getChb());
		CommandMoveTo cmt = new CommandMoveTo(iyp.getIndice(), iyp.getPosition());
		
		Vector<Command> comandos = new Vector<Command>();
		comandos.add(chbsToReturn.getChb());
		comandos.add(cmt);
		return comandos;
	}

	/**
	 * Obtiene el mejor pase ordenandolos segun el criterio de ordenacion de la clase CommandHitBallSimulated.
	 * Si esta en campo propio usa todos los pases de maxima potencia para llegar antes al campo contrario.
	 * Si esta en campo contrario usa los pases mas seguros en cuanto a diferencia de iteraciones para ser
	 * recuperados
	 * @param gs
	 * @param comandosSimulados
	 * @return
	 */
	private static CommandHitBallSimulated obtenerMejorPase(GameSituations gs, Vector<CommandHitBallSimulated> comandosSimulados) {
		Collections.sort(comandosSimulados);

		if(gs.ballPosition().getY() <= 0) {
			double potencia = comandosSimulados.firstElement().getChb().getHitPower();

			Vector<CommandHitBallSimulated> comandosSimuladosDeIgualPotencia = new Vector<CommandHitBallSimulated>();
			for(CommandHitBallSimulated chbs : comandosSimulados) {
				if(chbs.getChb().getHitPower() == potencia)
					comandosSimuladosDeIgualPotencia.add(chbs);
				else
					break;
			}

			return comandosSimuladosDeIgualPotencia.get(random.nextInt(comandosSimuladosDeIgualPotencia.size()));
		}
		else {
			double diferencia = comandosSimulados.firstElement().getIterationDifference();

			Vector<CommandHitBallSimulated> comandosSimuladosDeIgualDiferencia = new Vector<CommandHitBallSimulated>();
			for(CommandHitBallSimulated chbs : comandosSimulados) {
				if(chbs.getIterationDifference() == diferencia)
					comandosSimuladosDeIgualDiferencia.add(chbs);
				else
					break;
			}

			return comandosSimuladosDeIgualDiferencia.get(random.nextInt(comandosSimuladosDeIgualDiferencia.size()));
		}
	}
}
